---
title: Custom Domains
description: Configure custom domains in your components.
---

import { Tabs, TabItem } from '@astrojs/starlight/components';

You can configure custom domains and subdomains for your frontends, APIs, services, or routers in SST.

:::note
SST currently supports configuring custom domains for AWS components.
:::

By default, these components auto-generate a URL. You can pass in the `domain` to use your custom domain.

<Tabs>
  <TabItem label="Frontend">
  ```ts title="sst.config.ts" {2}
  new sst.aws.Nextjs("MyWeb", {
    domain: "example.com"
  });
  ```
  </TabItem>
  <TabItem label="API">
  ```ts title="sst.config.ts" {2}
  new sst.aws.ApiGatewayV2("MyApi", {
    domain: "api.example.com"
  });
  ```
  </TabItem>
  <TabItem label="Service">
  ```ts title="sst.config.ts" {6}
  const vpc = new sst.aws.Vpc("MyVpc");

  new sst.aws.Cluster("MyCluster", {
    vpc,
    loadBalancer: {
      domain: "example.com"
    }
  });
  ```
  </TabItem>
  <TabItem label="Router">
  ```ts title="sst.config.ts" {2}
  new sst.aws.Router("MyRouter", {
    domain: "example.com"
  });
  ```
  </TabItem>
</Tabs>

SST supports a couple of DNS providers automatically. These include AWS Route 53, Cloudflare, and Vercel. Other providers will need to be manually configured.

We'll look at how it works below.

---

##### Redirect www to apex domain

A common use case is to redirect `www.example.com` to `example.com`. You can do this by:

```ts title="sst.config.ts" {3,4}
new sst.aws.Router("MyRouter", {
  domain: {
    name: "example.com",
    redirects: ["www.example.com"]
  }
});
```

---

##### Add subdomains

You can add subdomains to your domain. This is useful if you want to use a `Router` to route a subdomain to a separate resource.

```ts title="sst.config.ts" {3,4,11}
const router = new sst.aws.Router("MyRouter", {
  domain: {
    name: "example.com",
    aliases: ["*.example.com"]
  }
});

new sst.aws.Nextjs("MyWeb", {
  router: {
    instance: router,
    domain: "docs.example.com"
  }
});
```

Here if a user visits `docs.example.com`, they'll kept on the alias domain and be served the docs site.

:::tip
You can use the `Router` component to centrally manage domains and routing for your
app. [Learn more](/docs/configure-a-router).
:::

However, this does not match `docs.dev.example.com`. For that, you'll need to add `*.dev.example.com` as an alias.

---

## How it works

Configuring a custom domain is a two step process.

1. Validate that you own the domain. For AWS you do this by [creating an ACM certificate](https://docs.aws.amazon.com/acm/latest/userguide/domain-ownership-validation.html) and validating it by:
   - Setting a DNS record with your domain provider.
   - Verifying through an email sent to the domain owner.
2. Add the DNS records to route your domain to your component.

SST can perform these steps automatically for the supported providers through a concept of _adapters_. These create the above DNS records on a given provider.

---

## Adapters

You can use a custom domain hosted on any provider. SST supports domains on AWS, Cloudflare, and Vercel automatically.

---

### AWS

By default, if you set a custom domain, SST assumes the domain is configured in AWS Route 53 in the same AWS account.

```js
{
  domain: {
    name: "example.com"
  }
}
```

This is the same as using the [`sst.aws.dns`](/docs/component/aws/dns/) adapter.

```js
{
  domain: {
    name: "example.com",
    dns: sst.aws.dns()
  }
}
```

If you have the same domain in multiple hosted zones in Route 53, you can specify the hosted zone.

```js {5}
{
  domain: {
    name: "example.com",
    dns: sst.aws.dns({
      zone: "Z2FDTNDATAQYW2"
    })
  }
}
```

If your domains are hosted on AWS but in a separate AWS account, you'll need to follow the [manual setup](#manual-setup).

---

### Vercel

If your domains are hosted on [Vercel](https://vercel.com), you'll need to do the following.

1. [Add the Vercel provider to your app](/docs/component/vercel/dns/#configure-provider).

   ```bash
   sst add @pulumiverse/vercel
   ```

2. Set the **`VERCEL_API_TOKEN`** in your environment. You might also need to set the `VERCEL_TEAM_ID` if the domain belongs to a team.

   ```bash
   export VERCEL_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
   ```

3. Use the [`sst.vercel.dns`](/docs/component/vercel/dns/) adapter.

   ```js
   {
     domain: {
       name: "example.com",
       dns: sst.vercel.dns()
     }
   }
   ```

---

### Cloudflare

If your domains are hosted on [Cloudflare](https://developers.cloudflare.com/dns/), you'll need to do the following.

1. Add the Cloudflare provider to your app.

   ```bash
   sst add cloudflare
   ```

2. Set the **`CLOUDFLARE_API_TOKEN`** in your environment.

   ```bash
   export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
   export CLOUDFLARE_DEFAULT_ACCOUNT_ID=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
   ```

   To get your API tokens, head to the [API Tokens section](https://dash.cloudflare.com/profile/api-tokens) of your Cloudflare dashboard and create one with the **Edit zone DNS** policy.

   The Cloudflare providers need these credentials to deploy your app in the first place, which means they can't be set using the `sst secret` CLI.

   If you are auto-deploying your app through the [SST Console](console.mdx#autodeploy) or through your CI, you'll need to set these as environment variables.


3. Use the [`sst.cloudflare.dns`](/docs/component/cloudflare/dns/) adapter.

   ```js
   {
     domain: {
       name: "example.com",
       dns: sst.cloudflare.dns()
     }
   }
   ```

---

## Manual setup

If your domain is on a provider that is not supported above, or is in a separate AWS account; you'll need to verify that you own the domain and set up the DNS records on your own.

To manually set up a domain on an unsupported provider, you'll need to:

1. [Validate that you own the domain](https://docs.aws.amazon.com/acm/latest/userguide/domain-ownership-validation.html) by creating an ACM certificate. You can either validate it by setting a DNS record or by verifying an email sent to the domain owner.

   :::note
   For CloudFront distributions, the certificate needs to be created in `us-east-1`.
   :::

   If you are configuring a custom domain for a CloudFront distribution, the ACM certificate that's used to prove that you own the domain needs be created in the `us-east-1` region.

   For all the other components, like ApiGatewayV2 or Cluster, can be created in any region.

2. Once validated, set the certificate ARN as the `cert` and set `dns` to `false`.

   ```js
   {
     domain: {
       name: "domain.com",
       dns: false,
       cert: "arn:aws:acm:us-east-1:112233445566:certificate/3a958790-8878-4cdc-a396-06d95064cf63"
     }
   }
   ```

3. Add the DNS records in your provider to point to the CloudFront distribution, API Gateway, or load balancer URL.
